﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Linq;
using System.Text;
using APC.Common;

namespace APC
{
    class RawMaterials
    {

        #region Enum

        public enum eActionType { TypeNew, TypeEdit, TypeDelete }
        public enum eItemType { TypeRawMaterial, TypeSum }
        public enum eRecordStatus { IsNotChanged, IsAdded, IsEdited, IsDeleted } //A rawmaterial related as an ingridient to an recipe can be either added, edited (procent) or removed
 
        #endregion

        #region Declarations

        private DataHandlingDataContext ctx;

        #endregion

        #region Properties

        public Int32 Id
        {
            get { return this._Id; }
            set { this._Id = value; }
        }
        private Int32 _Id;

        public Int32 RecipeId
        {
            get { return this._RecipeId; }
            set { this._RecipeId = value; }
        }
        private Int32 _RecipeId;

        public int TagListeId
        {
            set { _TagListeId = value; }
            get { return _TagListeId; }
        }
        private int _TagListeId = 0;

        public int TagListeGroupId
        {
            set { _TagListeGroupId = value; }
            get { return _TagListeGroupId; }
        }
        private int _TagListeGroupId = 0;

        public int LocationPosition
        {
            set { _LocationPosition = value; }
            get { return _LocationPosition; }
        }
        public int _LocationPosition;

        public int LocationId
        {
            set { _LocationId = value; }
            get { return _LocationId; }
        }
        public int _LocationId;

        private int _ = 0;

        public Decimal AmountProcent
        {
            get { return this._AmountProcent; }
            set { this._AmountProcent = value; }
        }
        private Decimal _AmountProcent;

        public decimal Tolerance
        {
            get { return this._Tolerance; }
            set { this._Tolerance = value; }
        }
        private decimal _Tolerance;

        public Int64 SetPointKg
        {
            get { return this._SetPointKg; }
            set { this._SetPointKg = value; }
        }
        private Int64 _SetPointKg;

        /// <summary>
        /// RawMaterialGroupId
        /// </summary>
        public Int64 GroupId
        {
            get { return this._GroupId; }
            set { this._GroupId = value; }
        }
        private Int64 _GroupId;

        public string LocationName
        {
            get { return this._LocationName; }
            set { this._LocationName = value; }
        }
        private string _LocationName;

        public String LocationsTypeName
        {
            get { return this._LocationsTypeName; }
            set { this._LocationsTypeName = value; }
        }
        private String _LocationsTypeName;

        public String Name
        {
            get { return this._Name; }
            set { this._Name = value; }
        }
        private String _Name;

        public String Number
        {
            get { return this._Number; }
            set { this._Number = value; }
        }
        private String _Number;

        /// <summary>
        /// Set backcolor of listviewitem depending on related TagListeGroupId
        /// </summary>
        public String BackColor
        {
            get { return this._BackColor; }
            set { this._BackColor = value; }
        }
        private String _BackColor;

        public String ColorMap
        {
            get { return this._ColorMap; }
            set { this._ColorMap = value; }
        }
        private String _ColorMap;

        public string Density
        {
            get { return this._Density; }
            set { this._Density = value; }
        }
        private string _Density;

        public Boolean IsSaved
        {
            set { _IsSaved = value; }
            get { return _IsSaved; }
        }
        private Boolean _IsSaved = false;

        /// <summary>
        /// If rawmaterial has 0 or more than one location, user must select the location used for order
        /// </summary>
        public int NumberOfLocations
        {
            set { _NumberOfLocations = value; }
            get { return _NumberOfLocations; }
        }
        private int _NumberOfLocations = -1;

        /// <summary>
        /// Number of 'clean' batches to flush producction line to avoid contamination
        /// </summary>
        public int BatchFlush
        {
            set { _BatchFlush = value; }
            get { return _BatchFlush; }
        }
        private int _BatchFlush = 0;

        /// <summary>
        /// Status of a rawmaterial in relation to an recipe
        /// </summary>
        public eRecordStatus RecordStatus
        {
            set { _RecordStatus = value; }
            get { return _RecordStatus; }
        }
        private eRecordStatus _RecordStatus;

        /// <summary>
        /// Enum: TypeSave, TypeUpdate, TypeDelete
        /// </summary>
        public eActionType ActionType
        {
            get { return _ActionType; }
            set { this._ActionType = value; }
        }
        private eActionType _ActionType;

        /// <summary>
        /// Enum: TypeRawMaterial, TypeSum
        /// </summary>
        public eItemType ItemType
        {
            get { return _ItemType; }
            set { this._ItemType = value; }
        }
        private eItemType _ItemType;

        public List<RawMaterielLocation> RawMaterialLocationCollection
        {
            set { this._RawMaterialLocationCollection = value; }
            get { return this._RawMaterialLocationCollection; }
        }
        private List<RawMaterielLocation> _RawMaterialLocationCollection = null;

        public List<GetRawMaterialLocationsResult> RawMaterialLocations
        {
            set { this._RawMaterialLocations = value; }
            get { return this._RawMaterialLocations; }
        }
        private List<GetRawMaterialLocationsResult> _RawMaterialLocations;

        /// <summary>
        /// Returns full list of all raw materials
        /// </summary>
        public List<RawMaterial> RawMaterialList
        {
            set { this._RawMaterialList = value; }
            get {
                LoadRawMaterialList();
                return this._RawMaterialList; 
            }
        }
        private List<RawMaterial> _RawMaterialList;

        /// <summary>
        /// Returns full list of all raw materials in negative list
        /// </summary>
        public List<NegativeRawMaterial> RawMaterialNegativeList
        {
            set { this._RawMaterialNegativeList = value; }
            get
            {
                LoadRawMaterialNegativeList();
                return this._RawMaterialNegativeList;
            }
        }
        private List<NegativeRawMaterial> _RawMaterialNegativeList;

        /// <summary>
        /// Returns full list of all raw material groups
        /// </summary>
        public List<RawMaterialGroup> RawMaterialGroups
        {
            set { this._RawMaterialGroups = value; }
            get
            {
                LoadRawMaterialGroups();
                return this._RawMaterialGroups;
            }
        }
        private List<RawMaterialGroup> _RawMaterialGroups;

        #endregion

        #region Constructors

        public RawMaterials(Int32 Id)
        {
            this._Id = Id;
            this.LoadRawMaterial();
            this.LoadRawMaterialList();
            this.LoadRawMaterialLocationList();

        }

        public RawMaterials(Int32 Id, bool b = false)
        {
            this._Id = Id;
            this.LoadRawMaterial();
        }

        /// <summary>
        /// Empty constructor
        /// </summary>
        public RawMaterials()
        {

        }

        public RawMaterials(bool LoadLists)
        {
            this.LoadRawMaterialList();
            this.LoadRawMaterialGroups();
            this.LoadRawMaterialLocationList();

        }

        #endregion

        #region Methods

        /// <summary>
        /// Loads selected RawMatrial on its Id
        /// </summary>
        private void LoadRawMaterial()
        {
            ctx = new DataHandlingDataContext(new Data().ConnectionString);  
      
          using (ctx)
          {
 
              var query = (from rm in ctx.RawMaterials
                           where rm.Id == _Id
                           select new
                           {
                               Name = rm.Name,
                               MaterialNumber = rm.MaterialNumber,
                               Density = rm.Density,
                               RawMaterialGroupId = rm.RawMaterialGroupId,
                           }).FirstOrDefault();

              this._Name = query.Name;
              this._Number = query.MaterialNumber;
              this._Density = query.Density;
              this._GroupId = Convert.ToInt64(query.RawMaterialGroupId);
              this._ItemType = eItemType.TypeRawMaterial;
              this._IsSaved = true;
             
             
              //List all Locations for selected Raw Material
              var queryI = from var3 in ctx.GetRawMaterialLocations(Convert.ToInt32(this._Id))
                           select var3;

              this._RawMaterialLocations = queryI.ToList<APC.Common.GetRawMaterialLocationsResult>();
          }
        }

        /// <summary>
        /// Returns full list of all raw material
        /// </summary>
        private void LoadRawMaterialList()
        {
            ctx = new DataHandlingDataContext(new Data().ConnectionString);

            using (ctx)
            {
                var query = (from r in ctx.RawMaterials
                            orderby r.RawMaterialGroupId ascending
                            select r);

                if (query != null)
                {
                    this._RawMaterialList = query.ToList<RawMaterial>();
                }
            }
        }

        /// <summary>
        /// Returns list of raw material on negative list for selected recipe
        /// </summary>
        private void LoadRawMaterialNegativeList()
        {
            ctx = new DataHandlingDataContext(new Data().ConnectionString);

            using (ctx)
            {
                var query = (from n in ctx.NegativeRawMaterials
                             select n);

                if (query != null)
                {
                    this._RawMaterialNegativeList = query.ToList<NegativeRawMaterial>();
                }

            }
        }

        private void LoadRawMaterialLocationList()
        {
            ctx = new DataHandlingDataContext(new Data().ConnectionString);

            using (ctx)
            {
                var query = (from r in ctx.RawMaterials
                             orderby r.RawMaterialGroupId ascending
                             select r);

                this._RawMaterialList = query.ToList<RawMaterial>(); // query.ToList<GetRawMaterialListResult>();
            }
        }

        public List<RawMaterialOnLocation> LoadRawMaterialOnLocationList()
        {
            List<RawMaterialOnLocation> lst;

            ctx = new DataHandlingDataContext(new Data().ConnectionString);

            using (ctx)
            {
                var query = (from rml in ctx.RawMaterialsLocations
                             from rm in ctx.RawMaterials
                             where rml.RawMateralId == rm.Id
                             select new 
                             { 
                             RawMaterialId = rm.Id,
                             LocationId = rml.LocationsId,
                             RawMaterialName = rm.Name,
                             RawMaterialNumber = rm.MaterialNumber
                             }).Select(x => new RawMaterialOnLocation()
                             {
                                 RawMaterialId = x.RawMaterialId,
                                 LocationId = (int)x.LocationId,
                                 RawMaterialName = x.RawMaterialName,
                                 RawMaterialNumber = x.RawMaterialNumber
                             }).ToList();

                            

                lst = query;

                return lst;
            }

        }

        /// <summary>
        /// Returns full list of all raw material groups
        /// </summary>
        private void LoadRawMaterialGroups()
        {
            ctx = new DataHandlingDataContext(new Data().ConnectionString);

            using (ctx)
            {
                var query = from var3 in ctx.RawMaterialGroups
                            select var3;

                this._RawMaterialGroups = query.ToList<RawMaterialGroup>();
            }
        }

        //public void Delete()
        //{
        //    if (ctx == null)
        //    {
        //        ctx = new DataHandlingDataContext(new Data().ConnectionString);
        //    }
        //    ctx.ExecuteCommand("UPDATE RawMaterial SET Active = 0 WHERE Id = " + _Id);
        //}

        public void Save()
        {
            Int32 RawMaterialId = 0;
            Log log = new Log();

            try
            {
                if (ctx == null)
                {
                    ctx = new DataHandlingDataContext(new Data().ConnectionString);
                }

                using (ctx)
                {

                    APC.Common.RawMaterial rm;

                    switch (this._ActionType)
                    {
                        case eActionType.TypeNew:
                            rm = new APC.Common.RawMaterial();
                            rm.Density = _Density;
                            rm.MaterialNumber = _Number;
                            rm.Name = _Name;
                            rm.RawMaterialGroupId = Convert.ToInt32(_GroupId);
                            rm.Active = true;
                            ctx.RawMaterials.InsertOnSubmit(rm);
                            ctx.SubmitChanges(); //Save to database
                            RawMaterialId = rm.Id; //Return new Id for saving related locations
                            break;

                        case eActionType.TypeEdit:
                            rm = ctx.RawMaterials.Single(u => u.Id == _Id);
                            rm.Id = _Id;
                            rm.Density = _Density;
                            rm.MaterialNumber = _Number;
                            rm.Name = _Name;
                            rm.RawMaterialGroupId = Convert.ToInt32(_GroupId);
                            ctx.SubmitChanges(); //Save to database
                            RawMaterialId = _Id;
                            break;

                        case eActionType.TypeDelete:
                            rm = ctx.RawMaterials.Single(u => u.Id == _Id);
                            rm.Active = false;
                            ctx.SubmitChanges(); //Save to database
                            break;
                    }

                    //Append to logfile
                   
                    log.UserId = "sys";
                    log.ObjectName = "RawMaterial";
                    log.ObjectId = RawMaterialId.ToString();
                    log.ObjectChangeType = _ActionType.ToString();
                    log.LogMessage = "";
                    log.Write();


                    if (this._ActionType != eActionType.TypeDelete)
                    {

                        foreach (RawMaterielLocation l in this._RawMaterialLocationCollection)
                        {
                            APC.Common.RawMaterialsLocation rl = new APC.Common.RawMaterialsLocation();

                            if (l.IsSaved == false)
                            {
                                rl.LocationsId = l.LocationId;
                                rl.RawMateralId = RawMaterialId;
                                ctx.RawMaterialsLocations.InsertOnSubmit(rl);

                                //Append to log
                                log.UserId = "sys";
                                log.ObjectName = "RawMaterialsLocation";
                                log.ObjectId = RawMaterialId.ToString();
                                log.ObjectChangeType = _ActionType.ToString();
                                log.LogMessage = "rm: " + RawMaterialId.ToString() + " loc: " + l.LocationId.ToString();
                                log.Write();
                            }
                        }
                        ctx.SubmitChanges(); //Save to database        
                    }
                }                 
            }
            catch
            {
                //Write to log!
            }
            
  
        }

        #endregion

    }

    class RawMaterialOnLocation
    {

        #region Properties

        public string RawMaterialName
        {
            get { return this._RawMaterialName; }
            set { this._RawMaterialName = value; }
        }
        private string _RawMaterialName;

        public string RawMaterialNumber
        {
            get { return this._RawMaterialNumber; }
            set { this._RawMaterialNumber = value; }
        }
        private string _RawMaterialNumber;

        public Int32 LocationId
        {
            get { return this._LocationId; }
            set { this._LocationId = value; }
        }
        private Int32 _LocationId;

        public Int32 RawMaterialId
        {
            get { return this._RawMaterialId; }
            set { this._RawMaterialId = value; }
        }
        private Int32 _RawMaterialId;

       #endregion
    }

}
